package services

import (
	"context"
	"encoding/json"
	"log"
	"saasems/models" // Add this import
	"time"

	"github.com/Knetic/govaluate"
	"github.com/segmentio/kafka-go"
)

type RuleEngine struct {
	consumer     *kafka.Reader
	rulesRepo    RuleRepository
	deviceClient DeviceServiceClient
	ticketClient TicketServiceClient
}

type RuleRepository interface {
	GetActiveRulesByTenant(tenantID string) ([]models.BusinessRule, error)
}

func NewRuleEngine(brokers []string, topic string, groupID string, repo RuleRepository,
	deviceClient DeviceServiceClient, ticketClient TicketServiceClient) *RuleEngine {
	return &RuleEngine{
		consumer: kafka.NewReader(kafka.ReaderConfig{
			Brokers: brokers,
			Topic:   topic,
			GroupID: groupID,
			MaxWait: 1 * time.Second,
		}),
		rulesRepo:    repo,
		deviceClient: deviceClient,
		ticketClient: ticketClient,
	}
}

func (e *RuleEngine) Start(ctx context.Context) {
	go func() {
		for {
			msg, err := e.consumer.FetchMessage(ctx)
			if err != nil {
				continue
			}

			var event map[string]interface{}
			if err := json.Unmarshal(msg.Value, &event); err != nil {
				continue
			}

			tenantID := event["tenant_id"].(string)
			rules, _ := e.rulesRepo.GetActiveRulesByTenant(tenantID)

			for _, rule := range rules {
				if evaluateCondition(rule.ConditionExpr, event) {
					e.executeActions(rule.Actions, event)
				}
			}

			e.consumer.CommitMessages(ctx, msg)
		}
	}()
}

func evaluateCondition(expr string, data map[string]interface{}) bool {
	expression, err := govaluate.NewEvaluableExpression(expr)
	if err != nil {
		log.Printf("条件表达式解析失败: %v", err)
		return false
	}
	result, err := expression.Evaluate(data)
	if err != nil {
		log.Printf("条件评估失败: %v", err)
		return false
	}
	return result == true
}

func (e *RuleEngine) executeActions(actions []models.RuleAction, data map[string]interface{}) {
	for _, action := range actions {
		payload, ok := action.Payload.(map[string]interface{})
		if !ok {
			log.Printf("Invalid payload format for action: %v", action.ActionType)
			continue
		}

		switch action.ActionType {
		case "device_control":
			deviceID := data["device_id"].(string)
			command := payload["command"].(string)
			err := e.deviceClient.ControlDevice(context.Background(), deviceID, command)
			if err != nil {
				log.Printf("设备控制失败: %v", err)
			}
		case "create_ticket":
			title := payload["title"].(string)
			description := payload["description"].(string)
			_, err := e.ticketClient.CreateTicket(context.Background(), title, description, "紧急")
			if err != nil {
				log.Printf("工单创建失败: %v", err)
			}
		}
	}
}
